//
//  ZDefsPrivate.h
//  Part of Z-Way.C library
//
//  Created by Alex Skalozub on 1/26/12.
//  Based on Z-Way source code written by Christian Paetz and Poltorak Serguei
//
//  Copyright (c) 2012 Z-Wave.Me
//  All rights reserved
//  info@z-wave.me
//
//  This source file is subject to the terms and conditions of the
//  Z-Wave.Me Software License Agreement which restricts the manner
//  in which it may be used.
//

#ifndef zway_defs_private_h
#define zway_defs_private_h

#include "ZMalloc.h"
#include "ZErrors.h"
#include "ZDefsPublic.h"

// Platform dependent section related to z-way and not covered in z-commons

#if defined(__ESP32__)
#define ZWAY_SAVE_KNOWN_PIN_COUNT_MAX 60
#define ZWAY_SAVE_KNOWN_PIN_COUNT_MIN 50
#else
#define ZWAY_SAVE_KNOWN_PIN_COUNT_MAX 10000
#define ZWAY_SAVE_KNOWN_PIN_COUNT_MIN 9500
#endif

#if defined(_WINDOWS)
#define ZWAY_DEFAULT_COM_PORT_FOR_CONTROLER ZSTR("COM3")
#elif defined(__MACH__)
#define ZWAY_DEFAULT_COM_PORT_FOR_CONTROLER ZSTR("/dev/cu.SLAB_USBtoUART")
#elif defined(__FreeBSD__)
#define ZWAY_DEFAULT_COM_PORT_FOR_CONTROLER ZSTR("/dev/cuaU0")
#elif defined(__linux__)
#define ZWAY_DEFAULT_COM_PORT_FOR_CONTROLER ZSTR("/dev/ttyACM0")
#elif defined(__ESP32__)
#define ZWAY_DEFAULT_COM_PORT_FOR_CONTROLER ZSTR("UART1")
#endif

// ZJob defs

struct _ZJob;
typedef struct _ZJob *ZJob;

#define ZJobPayloadPtr(job) ((const ZWBYTE *)((job->payload_size > FIXED_PAYLOAD_SIZE) ? (job->payload_ptr) : (job->payload)))
#define ZJobInnerPayloadPtr(job, inner) (ZJobPayloadPtr(job) + job->inner_payload_offset[inner])
#define ZJobInnerPayloadSize(job, inner) (job->inner_payload_size[inner])

struct _ZJobCallbackListEntry;
typedef struct _ZJobCallbackListEntry *ZJobCallbackListEntry;

// ZJobList defs

struct _ZJobList;
typedef struct _ZJobList *ZJobList;

struct _ZJobListEntry;
typedef struct _ZJobListEntry *ZJobListEntry;

typedef ZWBOOL (*ZJobListFilter)(const ZJob job);

// ZQueueEntry defs

struct _ZQueueEntry;
typedef struct _ZQueueEntry *ZQueueEntry;

// ZTimer defs
// ZTimer struct is defined in public include file
struct _ZTimerListEntry;
typedef struct _ZTimerListEntry *ZTimerListEntry;
struct _ZTimerList;
typedef struct _ZTimerList *ZTimerList;

// ZBufferedCommand defs

struct _ZBufferedCommand;
typedef struct _ZBufferedCommand *ZBufferedCommand;

// ZFunctionClass defs

struct _ZFunctionClass;
typedef struct _ZFunctionClass ZFunctionClass;

typedef ZWError (*ZFunctionClassAck)(ZWay zway, ZJob job);
typedef ZWError (*ZFunctionClassResponse)(ZWay zway, ZJob job, size_t size, const ZWBYTE *data);
typedef ZWError (*ZFunctionClassCallback)(ZWay zway, ZJob job, size_t size, const ZWBYTE *data);
typedef ZWError (*ZFunctionClassTimeout)(ZWay zway, ZJob job);

// libS2 defs
struct _ZS2;
typedef struct _ZS2 *ZS2;

// ZDevice defs

struct _ZDevice;
typedef struct _ZDevice *ZDevice;

struct _ZDeviceListEntry;
typedef struct _ZDeviceListEntry *ZDeviceListEntry;

struct _ZDeviceList;
typedef struct _ZDeviceList *ZDeviceList;

struct _ZDeviceS2;
typedef struct _ZDeviceS2 *ZDeviceS2;

// ZInstance defs

struct _ZInstance;
typedef struct _ZInstance *ZInstance;

struct _ZInstanceListEntry;
typedef struct _ZInstanceListEntry *ZInstanceListEntry;

struct _ZInstanceList;
typedef struct _ZInstanceList *ZInstanceList;

// ZCommand defs

struct _ZCommand;
typedef struct _ZCommand *ZCommand;

struct _ZCommandListEntry;
typedef struct _ZCommandListEntry *ZCommandListEntry;

struct _ZCommandList;
typedef struct _ZCommandList *ZCommandList;

// ZCommandClass defs

enum _ZW_CC_CMD_TYPE
{
    ZW_CC_CMD_TYPE_SET,                // Set
    ZW_CC_CMD_TYPE_SET_NO_SUPERVISION, // Set that should not be encapsulated in Supervision - used if sending of a separate Get is simpler than handling the supervised Report emulation
    ZW_CC_CMD_TYPE_SET_NO_REPORT,      // Set without Supervision and no expected Report
    ZW_CC_CMD_TYPE_GET,                // Get
    ZW_CC_CMD_TYPE_GET_TRANSPORT,      // Supervision Get
    ZW_CC_CMD_TYPE_REPORT,             // Report from a device
    ZW_CC_CMD_TYPE_TRANSPORT,          // Transport
    ZW_CC_CMD_TYPE_UNKNOWN             // Unknown
};

typedef enum _ZW_CC_CMD_TYPE ZW_CC_CMD_TYPE;

struct _ZCommandClass;
typedef struct _ZCommandClass ZCommandClass;

typedef ZWError (*ZCommandClassInit)(ZWay zway, ZCommand command);
typedef ZWError (*ZCommandClassInterview)(ZWay zway, ZCommand command);
typedef ZWError (*ZCommandClassCommand)(ZWay zway, ZCommand command, ZWNODE node_id, ZWBYTE instance_id, ZWBYTE length, const ZWBYTE *data);
typedef ZW_CC_CMD_TYPE (*ZCommandClassCommandType)(ZWay zway, ZWBYTE command);
typedef ZWError (*ZCommandClassCommandSupervisionHandler)(ZWay zway, ZCommand command, ZWNODE node_id, ZWBYTE instance_id, ZWBYTE length, const ZWBYTE *data);
typedef ZWError (*ZCommandClassPostLoad)(ZWay zway, ZCommand command);
typedef void (*ZCommandClassTimer)(ZWay zway, ZCommand command);

// ZDeviceCallbackList defs

struct _ZDeviceCallbackListEntry;
typedef struct _ZDeviceCallbackListEntry *ZDeviceCallbackListEntry;

struct _ZDeviceCallbackList;
typedef struct _ZDeviceCallbackList *ZDeviceCallbackList;

// ZNonceList defs

struct _ZNonce;
typedef struct _ZNonce *ZNonce;

struct _ZNonceList;
typedef struct _ZNonceList *ZNonceList;

struct _ZNonceListEntry;
typedef struct _ZNonceListEntry *ZNonceListEntry;

// misc I/O flags

enum _FrameTypes 
{
    SOF = 0x01,
    ACK = 0x06,
    NAK = 0x15,
    CAN = 0x18
};

#define REQUEST 0x00
#define RESPONSE 0x01

#define MAGIC_LEN 29

#define COMMAND_CLASS_MARK 0xEF
#define COMMAND_CLASS_EXT  0xF1

enum _NodeType
{
    CONTROLLER = 0x01,          // Node is a portable controller
    STATIC_CONTROLLER = 0x02,   // Node is a static controller
    SLAVE = 0x03,               // Node is a slave
    ROUTING_SLAVE = 0x04        // Node is a slave with routing capabilities
};

#define ZW_NODE_INFO_PROTOCOL_SPECIFIC_SPEED_40K_MASK   0x100000
#define ZW_NODE_INFO_PROTOCOL_SPECIFIC_SPEED_100K_MASK	0x000001

#ifdef DEBUG

void zway_debug_log_error(const ZWay zway, ZWError err, ZWError opt, const char *func, const char *file, int line);
#define LOG_ERR(r)	zway_debug_log_error(zway, r, NoError, #r, __FILE__, __LINE__)
#define LOG_ERR_OPT(r)  zway_debug_log_error(zway, r, NotSupported, #r, __FILE__, __LINE__)

#else

void zway_debug_log_error(const ZWay zway, ZWError err, ZWError opt, const char *func);
#define LOG_ERR(r)	zway_debug_log_error(zway, r, NoError, #r)
#define LOG_ERR_OPT(r)  zway_debug_log_error(zway, r, NotSupported, #r)

#endif // DEBUG

#define CHECK_SIZE(where, actual, expected) if ((unsigned long)(expected) > (unsigned long)(actual)) { \
    return _zway_log_error_short_size(zway, where, expected, actual); \
}

#endif
